package com.atguigu.feature.lambda;

import org.junit.Test;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * Created by Smexy on 2024/4/2
 */
public class Demo01LambdaTest {

    @Test
    public void testNewThreadByInnerClass() {
        // 使用传统语法创建新的线程（匿名内部类）
        // 1、创建 Runnable 类型的对象，封装的新线程所要执行的操作
        // ※ Lambda 表达式在简化代码背后，体现了一种『函数式编程』的思想
        // 封装新线程操作，真正关心的就是操作本身，对于创建对象、实现接口中的抽象方法……其实都不关心
        // 如果没有 Lambda 表达式，由于 Java 语法的要求和限制，必须写一些和操作无关的代码
        // 面向对象的基本要求：通过对象调用方法（但是当我们只需要方法内的操作时，创建对象就显得多余）
        // 函数式编程：既然特定的场景下只关心函数内的操作，那就简化函数之外的其它多余的语法
        // 函数式编程的极致体现：把函数当成对象来传递和使用
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello thread and lambda");
            }
        };

        // 2、把 Runnable 类型的对象传入 Thread 构造器并启动线程
        new Thread(runnable).start();
    }

    @Test
    public void testNewThreadByLambda() {
        // 使用 Lambda 表达式创建新的线程
        // 1、创建 Runnable 类型的对象，封装的新线程所要执行的操作
        Runnable runnable = () -> System.out.println("Hello thread and lambda");

        // 2、把 Runnable 类型的对象传入 Thread 构造器并启动线程
        new Thread(runnable).start();
    }

    @Test
    public void testLambdaBase01() {
        Demo02MyFunctionalInterface demo = () -> { System.out.println("Hello lambda ~~~"); };

        demo.showName();
    }

    @Test
    public void testLambdaBase02() {
        Demo03ShowNameWithArgs demo = (int demoAge, String demoName) -> {
            System.out.println("demoAge = " + demoAge);
            System.out.println("demoName = " + demoName);
        };

        demo.showName(50, "harry");
    }

    @Test
    public void testLambdaBase03() {
        Demo04ShowNameWithReturn demo = () -> {
            return "Good name ~~~";
        };

        String name = demo.showName();
        System.out.println("name = " + name);
    }

    @Test
    public void testLambdaSimple01() {
        // Lambda 体中只有一条语句，可以省略大括号和分号
        // 简化前
        Demo02MyFunctionalInterface demo01 = () -> { System.out.println("Hello lambda ~~~"); };

        // 简化后
        Demo02MyFunctionalInterface demo02 = () -> System.out.println("Hello lambda ~~~");
        demo02.showName();
    }

    @Test
    public void testLambdaSimple02() {
        Demo04ShowNameWithReturn demo01 = () -> { return "Good name ~~~"; };

        Demo04ShowNameWithReturn demo02 = () -> "Good name ~~~";

        String name = demo02.showName();
        System.out.println("name = " + name);
    }

    @Test
    public void testLambdaSimple03() {
        Demo03ShowNameWithArgs demo = (int demoAge, String demoName) -> {
            System.out.println("demoAge = " + demoAge);
            System.out.println("demoName = " + demoName);
        };

        // 对照函数式接口中那个唯一的抽象方法，能够确定参数列表中参数的类型
        // 此时参数类型部分可以省略
        // void showName(int demoAge, String demoName);
        demo = (demoAge, demoName) -> {
            System.out.println("demoAge = " + demoAge);
            System.out.println("demoName = " + demoName);
        };

        demo.showName(50, "harry");
    }

    @Test
    public void testLambdaSimple04() {

        Demo05ShowNameGeneric<String> demo01 = (String value) -> {
            System.out.println("value = " + value);
        };

        // 参数类型通过推断出来能够确定，所以也可以省略
        Demo05ShowNameGeneric<String> demo02 = (value) -> {
            System.out.println("value = " + value);
        };

        demo02.showName("value value value ~~~");

        // 参数列表中如果只有一个参数，那么参数列表的小括号可以省略
        Demo05ShowNameGeneric<String> demo03 = value -> {
            System.out.println("value = " + value);
        };

        demo03.showName("value value value ~~~");
    }

    @Test
    public void testLambdaConsumer() {
        // 测试消费型接口
        Consumer<String> consumer = value -> {
            // 消费型接口，Lambda 体中没有返回值
            System.out.println("value = " + value);
        };

        consumer.accept("Good");
    }

    @Test
    public void testLambdaSupplier() {
        // 测试供给接口
        Supplier<String> supplier = () -> "result";

        String value = supplier.get();
        System.out.println("value = " + value);
    }

    @Test
    public void testLambdaPredicate() {
        // 测试判断型接口
        Predicate<String> predicate = value -> value.length() > 5;

        boolean testResult = predicate.test("Hel");
        System.out.println("testResult = " + testResult);
    }

    @Test
    public void testLambdaFunction() {
        // 测试功能型接口
        Function<String, Integer> function = string -> string.length();

        Integer len = function.apply("Good morning");
        System.out.println("len = " + len);
    }

}
